import RPi.GPIO as GPIO
import time
import argparse
import os

parser = argparse.ArgumentParser(description="pwm风扇 调试脚本")
parser.add_argument("--p", type=float, help="P 默认：5.0")
parser.add_argument("--i", type=float, help="I 默认：0.01")
parser.add_argument("--d", type=float, help="D 默认：2.0")
args = parser.parse_args()
print(f"p: {args.p} i: {args.i} d: {args.d}")

# 设置GPIO模式
GPIO.setmode(GPIO.BCM)

# 风扇控制引脚
FAN_PIN = 14

# PWM 频率（1kHz，避免噪音）
HZ = 1000

# 设置GPIO引脚为输出，并启用PWM功能
GPIO.setup(FAN_PIN, GPIO.OUT)
pwm = GPIO.PWM(FAN_PIN, HZ)  # 1000Hz的PWM频率
pwm.start(0)  # 初始占空比为0%

# 温度范围
TARGET_TEMP = 40  # 目标温度（PID 维持的温度）
MIN_TEMP = 30  # 最低温度 (摄氏度)
MAX_TEMP = 60  # 最高温度 (摄氏度)



# PID 控制参数
Kp = 5.0  # 比例增益
Ki = 0.01  # 积分增益
Kd = 4.0  # 微分增益

if args.p is not None:
    Kp = args.p
if args.i is not None:
    Ki = args.i
if args.d is not None:
    Kd = args.d

print(f"Kp: {Kp} Ki: {Ki} Kd: {Kd}")

# PID 变量
prev_error = 0  # 上一次的误差
integral = 0  # 误差的累积


def read_temperature():
    """ 读取树莓派CPU温度 """
    temp_file = "/sys/class/thermal/thermal_zone0/temp"
    with open(temp_file, "r") as file:
        temp = int(file.read()) / 1000.0  # 转换成摄氏度
    return temp


def pid_control(temp):
    """ 使用 PID 计算风扇速度 """
    global prev_error, integral

    # 计算误差（当前温度 - 目标温度）
    error = temp - TARGET_TEMP

    # 计算 P、I、D
    P = Kp * error
    integral += error
    I = Ki * integral
    D = Kd * (error - prev_error)

    # PID 计算得到新的占空比
    duty_cycle = P + I + D
    prev_error = error  # 更新误差

    # 限制占空比在 0-100 之间
    duty_cycle = max(1, min(100, int(duty_cycle)))

    pwm.ChangeDutyCycle(duty_cycle)
    print(f"Temp: {temp}°C, Error: {error:.1f}, Fan Speed: {duty_cycle}%")


try:
    while True:
        current_temp = read_temperature()  # 获取当前温度
        pid_control(current_temp)  # 使用 PID 调节风扇速度
        time.sleep(0.5)  # 每2秒检查一次温度

except KeyboardInterrupt:
    print("程序已停止")
finally:
    pwm.stop()
    GPIO.cleanup()  # 清理GPIO设置
